/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2007，所有权利保留。
 * 
 * 文件名：	OptionReader.java
 * 模块说明：	
 * 修改历史：
 * 2007-3-20 - lxm - 创建。
 */
package com.hd123.rumba.option.biz;

import java.util.ArrayList;
import java.util.List;

import net.sf.hibernate.HibernateException;

import com.hd123.rumba.domain.IDomain;
import com.hd123.rumba.exception.BusinessException;
import com.hd123.rumba.option.IOptionCollection;
import com.hd123.rumba.option.IOptionItem;
import com.hd123.rumba.option.IOptionMgr;
import com.hd123.rumba.runtime.IManager;
import com.hd123.rumba.runtime.NamingMgr;
import com.hd123.rumba.runtime.biz.BManager;
import com.hd123.rumba.user.IUser;

/**
 * 选项阅读器代理
 * <p>
 * 
 * 程序中大量存在使用选项的地方，在这种情况下程序设计者可能只关心某个或若干个具体选项的取值。设计此代理对象，其核心功能是提供便捷的取得指定选
 * 项取值。这种场景下，这个对象不会占用大量的内存资源，即每次读取选项取值都将重新查询数据库。<br>
 * 需要通过静态方法{@link #getReader}创建阅读器实例，需要指定域、选项类和用户（一般为当前登录用户）。阅读器将根据业务策略自动判断在目前情
 * 况下应该返回全局取值还是个性化取值。
 * 
 * @author lxm
 * 
 */
public class OptionReader extends BManager {

  @Override
  public IManager getPerzMgr() throws BusinessException {
    return this.getOptMgr();
  }

  private OptionReader() {
    super();
  }

  /**
   * 取得一个选项阅读器。
   * 
   * @param domain
   *          指定所属域。
   * @param optionalClass
   *          指定选项类。
   * @param user
   *          指定所属用户，一般传入当前登录用户。允许传入null，表示只读取全局取值。
   * @return 返回创建的选项阅读器。
   * @throws BusinessException
   */
  public static OptionReader getReader(IDomain domain, Class optionalClass, IUser user)
      throws BusinessException {
    assert domain != null;
    assert optionalClass != null;
    OptionReader reader = new OptionReader();
    reader.setDomain(domain);
    reader.setOptionalClass(optionalClass);
    reader.setUser(user);
    return reader;
  }

  /**
   * 读取指定选项取值。
   * 
   * @param name
   *          指定的选项名。
   * @return 返回选项取值。
   * @throws BusinessException
   * @throws HibernateException
   */
  public Object readValue(String name) throws BusinessException, HibernateException {
    return this.readValue(name, null);
  }

  /**
   * 读取指定选项取值。
   * 
   * @param name
   *          指定的选项名。
   * @param defValue
   *          指定默认取值，表示当无法取得取值的时候，比如没有设置，将返回该值。
   * @return 返回选项取值。
   * @throws BusinessException
   * @throws HibernateException
   */
  public Object readValue(String name, Object defValue) throws BusinessException,
      HibernateException {
    this.checkParameterNotNull(name, "name");

    IOptionCollection globalCol = getOptMgr().getCollectionByClass(domain, optionalClass, null);
    if (globalCol == null)
      globalCol = getOptMgr().createCollection(domain, optionalClass, null);

    IOptionCollection currentCol = globalCol;
    if (user != null && globalCol.getOnline().booleanValue()) {
      IOptionCollection userCol = getOptMgr().getCollectionByClass(domain, optionalClass, null);
      if (userCol != null && !userCol.getInherited().booleanValue())
        currentCol = userCol;
    }

    if (currentCol.getInherited().booleanValue())
      return defValue;
    IOptionItem item = currentCol.getItemByName(name);
    if (item == null)
      return defValue;
    else
      return item.getValue();
  }

  /**
   * 取得符合指定条件，且有效的（即有值的）选项名。
   * 
   * @param nameLike
   *          指定选项名类似于条件，通配符位于右边。例如传入"item"，等价于运算"<i>选项名</i> like 'item%'"。
   * @return 返回所有符合条件的选项名列表，若没有找到符合条件的，则返回空的列表。
   * @throws BusinessException
   * @throws HibernateException
   */
  public List<String> getNames(String nameLike) throws BusinessException, HibernateException {
    if (nameLike == null)
      nameLike = "";

    IOptionCollection globalCol = getOptMgr().getCollectionByClass(domain, optionalClass, null);
    if (globalCol == null)
      globalCol = getOptMgr().createCollection(domain, optionalClass, null);

    IOptionCollection currentCol = globalCol;
    if (user != null && globalCol.getOnline().booleanValue()) {
      IOptionCollection userCol = getOptMgr().getCollectionByClass(domain, optionalClass, null);
      if (userCol != null && !userCol.getInherited().booleanValue())
        currentCol = userCol;
    }

    List<String> names = new ArrayList();
    if (!currentCol.getInherited().booleanValue())
      for (int i = 0; i < currentCol.getItems().size(); i++) {
        String name = currentCol.getItems().get(i).getName();
        if (name.startsWith(nameLike))
          names.add(name);
      }
    return names;
  }

  /**
   * 取得对应的选项写入器。
   * 
   * @return
   * @throws BusinessException
   * @throws HibernateException
   * @see OptionWriter#getWriter
   */
  public OptionWriter createWriter() throws BusinessException, HibernateException {
    return OptionWriter.getWriter(domain, optionalClass, user);
  }

  private IDomain domain = null;
  private Class optionalClass = null;
  private IUser user = null;

  /** 属性：所属域 */
  public IDomain getDomain() {
    return domain;
  }

  private void setDomain(IDomain domain) {
    this.domain = domain;
  }

  /** 属性：所指向的选项类。 */
  public Class getOptionalClass() {
    return optionalClass;
  }

  private void setOptionalClass(Class optionalClass) {
    this.optionalClass = optionalClass;
  }

  /** 属性：所属用户 */
  public IUser getUser() {
    return user;
  }

  private void setUser(IUser user) {
    this.user = user;
  }

  private IOptionMgr optMgr = null;

  private IOptionMgr getOptMgr() throws BusinessException {
    if (optMgr == null)
      optMgr = (IOptionMgr) NamingMgr.getInstance().lookupMgr(IOptionMgr.class);
    return optMgr;
  }
}
